#include "../include/uart.h"
#include "../include/my_joystick.h"
#include "../include/thread_handling.h"
#include "../include/commands.h"
#include "../include/log.h"
#include "../include/type.h"
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#include <string.h>
#include<termios.h>
#include<fcntl.h>
#include<linux/joystick.h>

// 全局变量

bool pre_flag = false;            // 传输标志
            

// 声明线程句柄
pthread_t tid_joystick;
pthread_t tid_addVal;

void* pthread_joystick(void * arg);
void* pthread_addVal(void * arg);
// 主程序入口
int main(int argc, char* argv[]) {
    LOG_INFO("System starting up...");
    //初始状态定义
    host_ctr_cmd_g.headL = 0x0D;
    host_ctr_cmd_g.headH = 0x0A;
    host_ctr_cmd_g.cmd = JOYSTICK_CMD;
    host_ctr_cmd_g.stepmotor_ctr.dist = 0;
    host_ctr_cmd_g.servo_ctr.servo_head_x = 90;
    host_ctr_cmd_g.servo_ctr.servo_head_y = 45  ;
    host_ctr_cmd_g.servo_ctr.servo_fin_left_out = 90;
    host_ctr_cmd_g.servo_ctr.servo_fin_left_in = Servo_Fin_Left_In_init;
    host_ctr_cmd_g.servo_ctr.servo_fin_right_in = Servo_Fin_Right_In_init;
    host_ctr_cmd_g.servo_ctr.servo_fin_right_out = 90;

    //open() 返回文件描述符 uartfd，用于后续的串口操作。如果返回值小于0，表示打开设备失败。
    uartfd = open("/dev/myuart",O_RDWR|O_NOCTTY| O_NDELAY);//只读|程序不会成为这个设备的控制终端|非阻塞模式
    if(uartfd<0){
        LOG_ERR("open uart falid");
        uart_reconnect(&uartfd);
        LOG_ERR("open uart success");
    }
    uart_init(&uartfd);
    host_ctr_cmd_g.cmd = SHELL_OPEN; //通过打开 Shell，用户可以通过命令行界面与系统进行交互。包括输入命令来控制遥控设备。
    uart_send_command(&host_ctr_cmd_g,sizeof(host_ctr_cmd_g));

    joystick_fd=joystick_open("/dev/input/js0", 1);
    while(joystick_fd<0){
        LOG_ERR("open joystick failed.\n");
        sleep(10);
        joystick_close(joystick_fd);
        joystick_fd=joystick_open("/dev/input/js0", 1);
    }
    LOG_ERR("open joystick success\n");

    uart_send_data( "\n",1); //这行代码向 uartfd 指向的串行端口发送一个换行符。这通常用于串行通信中表示消息的结束或换行。
    uart_send_data( "nano_ctr\n",strlen("nano_ctr\n")); 
    sleep(5);

    host_ctr_cmd_g.cmd = POWER_OFF; //关电
    uart_send_command(&host_ctr_cmd_g,sizeof(host_ctr_cmd_g));

    joystick_result_code=ioctl(joystick_fd, JSIOCGAXES, &joystick_num_axes);//ioctl() 函数来自于 <sys/ioctl.h> 头文件  
    if (joystick_result_code == 0) {  
        LOG_DBG("joystick_num_axes:%d\n",joystick_num_axes);  
        if (joystick_num_axes> 0) {  
          joystick_axes_status= (AXES_T*)calloc(1,sizeof(AXES_T) );  
        }  
    } //使用 ioctl 系统调用获取操纵杆的轴数（number_of_axes）。

   joystick_result_code = ioctl(joystick_fd, JSIOCGBUTTONS, &joystick_num_buttons);  
    if (joystick_result_code != -1) {  
        LOG_DBG("joystick_num_buttons:%d\n", joystick_num_buttons);  
    }  //获取操纵杆的按钮数（number_of_btns），并记录到日志中

    if (ioctl(joystick_fd, JSIOCGNAME(sizeof(joystick_name)), joystick_name) < 0) {  
        LOG_DBG( "Unknown name");  
    }  //获取操纵杆的设备名称。
  
    LOG_DBG("joystick Name: %s\n", joystick_name);


   
    create_thread(&tid_joystick, pthread_joystick, &joystick_fd);
    create_thread(&tid_addVal, pthread_addVal, &joystick_fd);

    //监控串口连接的状态，如果连接丢失则尝试重新连接
    struct termios old_cfg;//将终端的相关配置存储在这里
    while(1){
        if(0>tcgetattr(uartfd,&old_cfg))
        {
            pre_flag = false;
            LOG_ERR("uart connection error\n");
        }
        if(pre_flag == false){
            uart_reconnect(&uartfd);
            while(0>tcgetattr(uartfd,&old_cfg)){
                uart_reconnect(&uartfd);
            }
            uart_init(&uartfd);
            host_ctr_cmd_g.cmd = SHELL_OPEN; //通过打开 Shell，用户可以通过命令行界面与系统进行交互。包括输入命令来控制遥控设备。
            uart_send_command(&host_ctr_cmd_g,sizeof(host_ctr_cmd_g));

            joystick_fd=joystick_open("/dev/input/js0", 1);
             while(joystick_fd<0){
            LOG_ERR("open joystick failed.\n");
            sleep(10);
            joystick_close(joystick_fd);
            joystick_fd=joystick_open("/dev/input/js0", 1);
            }
            LOG_ERR("open joystick success\n");
            pre_flag = true;
            uart_send_data( "\n",1); //这行代码向 uartfd 指向的串行端口发送一个换行符。这通常用于串行通信中表示消息的结束或换行。
            uart_send_data( "nano_ctr\n",10);
        }
        sleep(10);
    }
}
